Методы доступа к данным (PostgreSQL)
PostgreSQL читает данные страницами (pages), а не “по строкам”. Поэтому главный вопрос: сколько страниц прочитаем/запишем и какой паттерн I/O.
Связанные темы:
Планировщик запросов и EXPLAIN
ANALYZE и статистика планировщика
Основные методы сканирования
Seq Scan (последовательное сканирование)
-
Читает таблицу целиком (heap).
-
Часто быстрее индекса, если нужно вернуть большую долю таблицы (много строк) или таблица маленькая.
-
Риск: “случайно” просканировать гигантскую таблицу из-за неверного фильтра/плана.
Index Scan (индексное сканирование)
-
Идёт по индексу и для каждой найденной записи обычно читает соответствующую страницу heap.
-
Хорошо, когда возвращаем мало строк и фильтр селективный.
-
Может стать дорогим при большом числе попаданий: будет много случайных чтений heap.
Bitmap Index Scan + Bitmap Heap Scan
-
Сначала строит “битовую карту” подходящих TID, затем читает heap более пакетно.
-
Полезно, когда строк “не совсем мало”: не настолько селективно для Index Scan, но и не настолько много для Seq Scan.
-
Часто встречается при условиях с несколькими индексами (bitmap AND/OR).
Index Only Scan
-
Читает только индекс (heap не трогает), если видимость строк подтверждена (visibility map).
-
Сильно ускоряет read-heavy запросы, но зависит от того, как отрабатывает VACUUM, Autovacuum и bloat.
Что означает cost/rows в EXPLAIN
EXPLAIN показывает оценку, а не факт.
- cost — относительная “стоимость” узла.
- первое число: стоимость получить первую строку
-
второе число: стоимость получить все строки узлом
-
rows — ожидаемое число строк на узле (по статистике).
-
Если rows сильно расходится с фактом в EXPLAIN ANALYZE — см. ANALYZE и статистика планировщика.
Типовые причины “плохого” доступа
-
Низкая селективность фильтра ⇒ индекс не помогает.
-
Условие не использует индекс (функции по колонке, не тот оператор, несовместимый тип).
-
Устаревшая статистика ⇒ планировщик неверно оценивает rows.
-
Сильный bloat ⇒ лишние чтения страниц heap/индекса.
См. также: Планировщик запросов и EXPLAIN, Индексы в PostgreSQL, VACUUM, Autovacuum и bloat.